<template>
  <div id="app" style="height: 100vh; display: flex">
    <!-- 左侧拖拽面板 -->
    <div style="width: 200px; border-right: 1px solid #ccc; padding: 10px">
      <h3>节点面板</h3>
      <div
        v-for="node in nodePanel"
        :key="node.type"
        class="drag-node"
        draggable="true"
        @dragstart="onDragStart($event, node)"
        style="
          padding: 8px;
          margin-bottom: 10px;
          background: #f0f0f0;
          cursor: grab;
        "
      >
        {{ node.label }}
      </div>
      <el-button
        type="primary"
        @click="exportJson"
        style="margin-bottom: 10px; width: 100%"
        >保存</el-button
      >
      <div>
        <el-button
          type="danger"
          @click="removeSelectedNode"
          style="width: 100%"
          :disabled="!selectedNodeId"
          >删除选中节点</el-button
        >
      </div>
    </div>

    <!-- 画布容器 -->
    <div ref="containerRef" style="flex: 1; height: 100%"></div>

    <!-- 编辑弹窗 -->
    <el-dialog v-model="showEditor" title="编辑节点" width="400px">
      <el-form :model="editNode" label-width="80px">
        <el-form-item label="名称">
          <el-input v-model="editNode.text.value" />
        </el-form-item>
        <!-- <el-form-item label="角色">
          <el-radio-group
            v-model="editNode.properties.signType"
            @change="changeSign"
          >
            <el-radio :value="1">管理员</el-radio>
            <el-radio :value="2">岗位</el-radio>
          </el-radio-group>
        </el-form-item> -->
        <!-- <el-form-item label="审批人" v-if="editNode.properties.signType === 1">
          <el-select
            v-model="editNode.properties.approvers"
            clearable
            placeholder="请选择"
          >
            <el-option
              v-for="item in userList"
              :key="item.userId"
              :label="item.nickName"
              :value="item.userId"
            />
          </el-select>
        </el-form-item> -->
        <el-form-item label="审批人">
          <el-select
            v-model="editNode.properties.approvers"
            clearable
            placeholder="请选择"
          >
            <el-option
              v-for="item in userList1"
              :key="item.postId"
              :label="item.postName"
              :value="item.postId"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="审核模式">
          <el-radio-group v-model="editNode.properties.operType">
            <el-radio label="单人审核" :value="1"></el-radio>
            <el-radio label="多人审核" :value="2"></el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showEditor = false">取消</el-button>
        <el-button type="primary" @click="saveNode">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from "vue";
import LogicFlow from "@logicflow/core";
import { BpmnElement } from "@logicflow/extension";
import { ElMessage } from "element-plus";
const { proxy } = getCurrentInstance();

import "@logicflow/core/es/index.css";
import "@logicflow/extension/lib/style/index.css";
import {
  getAdminList,
  getActorList,
  getPostList,
  addStep,
} from "@/api/approve/approveProcess";
import useHuazhongStore from "../../../store/modules/huazhong";
const huazhong = useHuazhongStore();
const route = useRoute();
LogicFlow.use(BpmnElement);

const containerRef = ref(null);
const lf = ref(null);
const selectedNodeId = ref(null);

const showEditor = ref(false);
const editNode = ref({
  id: "",
  text: {
    value: "",
  },

  properties: {
    approvers: "",
    signType: 1,
    operType: 1,
  },
});

const userList = ref([]);
const userList1 = ref([]);
const nodePanel = [
  { type: "bpmn:startEvent", label: "发起人" },
  { type: "bpmn:userTask", label: "审批节点" },
  // { type: "bpmn:exclusiveGateway", label: "条件分支" },
];

// 监听单选
function changeSign(value) {
  console.log(value);
  editNode.value.properties.approvers = "";
  if (value === 1) {
    //管理员
    adminList();
  } else if (value === 2) {
    //角色
    actorList();
  }
}
adminList();
actorList();
// 单选为管理员
function adminList() {
  getAdminList().then((res) => {
    userList.value = res.data;
  });
}
//单选为角色
function actorList() {
  getPostList().then((res) => {
    userList1.value = res.data;
  });
}

let nodeIdCounter = 1;

function onDragStart(event, node) {
  event.dataTransfer.setData("node/type", node.type);
}

function onDrop(event) {
  event.preventDefault();
  const type = event.dataTransfer.getData("node/type");
  if (!type) return;

  const rect = containerRef.value.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;

  lf.value.addNode({
    id: `${type}_${nodeIdCounter++}`,
    type,
    x,
    y,
    text:
      type === "bpmn:startEvent"
        ? "发起人"
        : type === "bpmn:userTask"
        ? "审批节点"
        : "条件分支",
    properties: {
      approvers: "",
      signType: 1,
      operType: 1,
    },
  });
}

function onDragOver(event) {
  event.preventDefault();
}

onMounted(() => {
  nextTick(() => {
    lf.value = new LogicFlow({
      container: containerRef.value,
      grid: true,
      keyboard: true,
    });
    const approves = huazhong.approve ? JSON.parse(huazhong.approve) : {};
    if (approves.nodes?.length > 0) {
      updateNodeIdCounter(approves);
      console.log(nodeIdCounter, "nodeIdCounter");
    }

    lf.value.render(approves);

    lf.value.on("node:click", ({ data }) => {
      selectedNodeId.value = data.id;
      const nodeData = lf.value
        .getGraphData()
        .nodes.find((n) => n.id === data.id);
      editNode.value = JSON.parse(JSON.stringify(nodeData));
      showEditor.value = true;
    });

    containerRef.value.addEventListener("dragover", onDragOver);
    containerRef.value.addEventListener("drop", onDrop);
  });
});
function updateNodeIdCounter(graphData) {
  const allIds = graphData.nodes.map((n) => n.id);
  const max = allIds.reduce((max, id) => {
    const match = id.match(/_(\d+)/);
    if (match) {
      return Math.max(max, parseInt(match[1]));
    }
    return max;
  }, 0);

  nodeIdCounter = max + 1;
}

function saveNode() {
  lf.value.updateText(editNode.value.id, editNode.value.text.value);
  lf.value.setProperties(editNode.value.id, editNode.value.properties);
  showEditor.value = false;
}

function exportJson() {
  const data = lf.value.getGraphData();

  const sortedApprovals = getSortedApprovalNodes(data);
  console.log(sortedApprovals);
  const sendDate = {
    operatorId: route.query.id,
    nodes: sortedApprovals,
    edges: data.edges,
  };
  addStep(sendDate).then((res) => {
    huazhong.setApprove(JSON.stringify(sendDate));
    proxy.$modal.msgSuccess("保存成功");
  });
}
// 排序
// 获取 LogicFlow 图结构，并排序审批顺序用于后端
function getSortedApprovalNodes(graphData) {
  const nodeMap = new Map();
  const inDegreeMap = new Map();

  graphData.nodes.forEach((node) => {
    nodeMap.set(node.id, node);
    inDegreeMap.set(node.id, 0);
  });

  graphData.edges.forEach((edge) => {
    inDegreeMap.set(edge.targetNodeId, inDegreeMap.get(edge.targetNodeId) + 1);
  });

  const queue = [];
  const sorted = [];

  // 将入度为 0 的节点放入队列（如 startEvent）
  inDegreeMap.forEach((degree, id) => {
    if (degree === 0) queue.push(id);
  });

  while (queue.length > 0) {
    const currentId = queue.shift();
    const currentNode = nodeMap.get(currentId);
    sorted.push(currentNode);

    graphData.edges.forEach((edge) => {
      if (edge.sourceNodeId === currentId) {
        const targetId = edge.targetNodeId;
        inDegreeMap.set(targetId, inDegreeMap.get(targetId) - 1);
        if (inDegreeMap.get(targetId) === 0) queue.push(targetId);
      }
    });
  }
  return sorted.filter(
    (n) => n.type === "bpmn:startEvent" || n.type === "bpmn:userTask"
  );
}

function removeSelectedNode() {
  if (!selectedNodeId.value) {
    ElMessage.warning("请先选中一个节点");
    return;
  }
  lf.value.deleteNode(selectedNodeId.value);
  selectedNodeId.value = null;
  showEditor.value = false;
  ElMessage.success("已删除节点");
}
</script>

<style>
body,
html,
#app {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}
.drag-node {
  user-select: none;
}
</style>
